package com.rr.middle;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;

/**
 * https://leetcode.cn/problems/maximum-number-of-operations-with-the-same-score-ii/?envType=daily-question&envId=2024-06-08
 */
public class MaxOperations {

    private Set<String> cacheSet = new HashSet<>();

    public int maxOperations(int[] nums) {
        int[] result = new int[] {0};
        CompletableFuture<Void> feature1 =
            CompletableFuture.supplyAsync(() -> doGetOperation(2, nums.length - 1, 1, nums[0] + nums[1], nums))
                .thenAccept(a -> result[0] = Math.max(a, result[0]));
        CompletableFuture<Void> feature2 = CompletableFuture.supplyAsync(
                () -> doGetOperation(1, nums.length - 2, 1, nums[0] + nums[nums.length - 1], nums))
            .thenAccept(a -> result[0] = Math.max(a, result[0]));
        CompletableFuture<Void> feature3 = CompletableFuture.supplyAsync(
                () -> doGetOperation(0, nums.length - 3, 1, nums[nums.length - 1] + nums[nums.length - 2], nums))
            .thenAccept(a -> result[0] = Math.max(a, result[0]));
        CompletableFuture.allOf(feature1, feature2, feature3).join();
        return result[0];
    }

    private int doGetOperation(int left, int right, int operationNum, int target, int[] nums) {
        if (left >= right || !cacheSet.add(String.valueOf(left) + String.valueOf(right) + String.valueOf(target))) {
            return operationNum;
        }
        int result = operationNum;
        if (nums[left] + nums[right] == target) {
            result = Math.max(result, doGetOperation(left + 1, right - 1, operationNum + 1, target, nums));
        }
        if (nums[left] + nums[left + 1] == target) {
            result = Math.max(result, doGetOperation(left + 2, right, operationNum + 1, target, nums));
        }
        if (nums[right] + nums[right - 1] == target) {
            result = Math.max(result, doGetOperation(left, right - 2, operationNum + 1, target, nums));
        }
        return result;
    }
}
